package com.ruoyi.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.domain.dto.RoleDTO;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.OaProject;
import com.ruoyi.oa.domain.OaPurchaesPayment;
import com.ruoyi.oa.domain.vo.OaFinanceTravelVo;
import com.ruoyi.oa.domain.vo.OaHumanReplaceVo;
import com.ruoyi.oa.domain.vo.OaPurchaesPaymentVo;
import com.ruoyi.oa.service.IOaHumanClockService;
import com.ruoyi.workflow.service.IProcessInstanceService;
import com.ruoyi.workflow.service.IUserService;
import com.ruoyi.workflow.utils.WorkFlowUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaFinanceTripApplyBo;
import com.ruoyi.oa.domain.vo.OaFinanceTripApplyVo;
import com.ruoyi.oa.domain.OaFinanceTripApply;
import com.ruoyi.oa.mapper.OaFinanceTripApplyMapper;
import com.ruoyi.oa.service.IOaFinanceTripApplyService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 出差申请Service业务层处理
 *
 * @author zhoul
 * @date 2023-03-28
 */
@RequiredArgsConstructor
@Service
public class OaFinanceTripApplyServiceImpl implements IOaFinanceTripApplyService {

    private final OaFinanceTripApplyMapper baseMapper;

    private final IProcessInstanceService iProcessInstanceService;

    private final OaProjectServiceImpl oaProjectService;

    private final IUserService iUserService;

    private final IOaHumanClockService iOaHumanClockService;

    @Override
    public OaFinanceTripApplyVo queryById(String id) {
        OaFinanceTripApplyVo vo = baseMapper.selectVoById(id);
        WorkFlowUtils.setStatusFileValue(vo, vo.getId());
        return vo;
    }

    /**
     * 查询出差申请列表
     */
    @Override
    public TableDataInfo<OaFinanceTripApplyVo> queryPageList(OaFinanceTripApplyBo bo, PageQuery pageQuery) {
        LoginUser currentUser = LoginHelper.getLoginUser();
        List<RoleDTO> roles = currentUser.getRoles();
        if (CollectionUtil.isNotEmpty(roles)){
            List<RoleDTO> roleDTOS = roles.stream().filter(d -> d.getRoleId()==(116)||d.getRoleId()==(1)).collect(Collectors.toList());
            if (CollectionUtil.isEmpty(roleDTOS)){
                bo.setCreateUser(currentUser.getUsername());
            }
        }
        if (StringUtils.isNotBlank(bo.getCreateBy())) {
            String userName = iUserService.getUserNameByNickName(bo.getCreateBy());
            if (StringUtils.isNotBlank(userName)) {
                bo.setCreateBy(userName);
            }
        }
        List<OaFinanceTripApplyVo> oaFinanceTripApplyVos = baseMapper.queryByCondition(bo);
        //构造page
        Page<OaFinanceTripApplyVo> result = new Page<>();
        result.setTotal(oaFinanceTripApplyVos.size());
        oaFinanceTripApplyVos = oaFinanceTripApplyVos.subList((pageQuery.getPageNum() - 1) * pageQuery.getPageSize(), (pageQuery.getPageNum() * pageQuery.getPageSize()) > oaFinanceTripApplyVos.size() ? oaFinanceTripApplyVos.size() : pageQuery.getPageNum() * pageQuery.getPageSize());
        result.setRecords(oaFinanceTripApplyVos);
        result.setCurrent(pageQuery.getPageNum());
        result.setSize(pageQuery.getPageSize());

        List<OaFinanceTripApplyVo> voList = result.getRecords();

        //先过滤流程无关的条件，没搜到就返回
        if (CollectionUtil.isEmpty(voList)) {
            result.setRecords(voList);
            result.setTotal(voList.size());
            return TableDataInfo.build(result);
        }

        //再挂接上流程属性
        List<String> collectIds = voList.stream().map(OaFinanceTripApplyVo::getId).collect(Collectors.toList());
        WorkFlowUtils.setStatusListFileValue(voList, collectIds, "id");

        //过滤流程的状态
        if (StringUtils.isNotBlank(bo.getStatus())) {
            List<OaFinanceTripApplyVo> temp = new ArrayList<>();
            for (OaFinanceTripApplyVo vo : voList) {
                if (vo.getActBusinessStatus().getStatus().equals(bo.getStatus())) {
                    temp.add(vo);
                }
            }
            voList = temp;
        }
        //过滤流程的提交时间
        if (CollectionUtil.isNotEmpty(bo.getSubmitTimeList())) {
            voList = voList.stream().filter(d -> ObjectUtil.isNotEmpty(d.getActBusinessStatus().getCreateTime()))
                .filter(d -> {
                    if (d.getActBusinessStatus().getCreateTime().after(bo.getSubmitTimeList().get(0)) && d.getActBusinessStatus().getCreateTime().before(bo.getSubmitTimeList().get(1))) {
                        return true;
                    } else {
                        return false;
                    }
                }).collect(Collectors.toList());
        }

        // 筛选提交人
        if (StringUtils.isNotEmpty(bo.getCreateBy())) {
            String[] split = bo.getCreateBy().split(",");
            List<String> list = Arrays.asList(split);
            List<OaFinanceTripApplyVo> temp = new ArrayList<>();
            for (OaFinanceTripApplyVo vo : voList) {
                if (ObjectUtil.isNotEmpty(vo.getActBusinessStatus().getCreateTime()) && list.indexOf(vo.getActBusinessStatus().getCreateBy())!=-1) {
                    temp.add(vo);
                }
            }
            voList = temp;
        }
        Page<OaFinanceTripApplyVo> result2 = new Page<>();
        result2.setTotal(voList.size());

        int start = (pageQuery.getPageNum() - 1) * pageQuery.getPageSize();
        int end = Math.min(pageQuery.getPageNum() * pageQuery.getPageSize(), voList.size());
        voList = voList.subList(start, end);

        result2.setRecords(voList);
        result2.setCurrent(pageQuery.getPageNum());
        result2.setSize(pageQuery.getPageSize());
        return TableDataInfo.build(result2);
    }

    /**
     * 查询出差申请列表
     */
    @Override
    public List<OaFinanceTripApplyVo> queryList(OaFinanceTripApplyBo bo) {
        LambdaQueryWrapper<OaFinanceTripApply> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<OaFinanceTripApply> buildQueryWrapper(OaFinanceTripApplyBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OaFinanceTripApply> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getProjectName()), OaFinanceTripApply::getProjectName, bo.getProjectName());
        lqw.like(StringUtils.isNotBlank(bo.getTripReason()), OaFinanceTripApply::getTripReason, bo.getTripReason());
        lqw.like(StringUtils.isNotBlank(bo.getOriginPlace()), OaFinanceTripApply::getOriginPlace, bo.getOriginPlace());
        lqw.like(StringUtils.isNotBlank(bo.getDestination()), OaFinanceTripApply::getDestination, bo.getDestination());
        if (CollectionUtil.isNotEmpty(bo.getTripTimeList())) {
            lqw.le(OaFinanceTripApply::getStartDate, bo.getTripTimeList().get(0));
            lqw.ge(OaFinanceTripApply::getEndDate, bo.getTripTimeList().get(1));
        }
        lqw.ge(bo.getDurationMin() != null, OaFinanceTripApply::getDuration, bo.getDurationMin());
        lqw.le(bo.getDurationMax() != null, OaFinanceTripApply::getDuration, bo.getDurationMax());
        return lqw;
    }

    /**
     * 新增出差申请
     */
    @Override
    public OaFinanceTripApplyBo insertByBo(OaFinanceTripApplyBo bo) {
        //设置数据范围
        LoginUser currentUser = LoginHelper.getLoginUser();
        bo.setDeptId(currentUser.getDeptId());
        bo.setUserId(currentUser.getUserId());

        OaFinanceTripApply add = BeanUtil.toBean(bo, OaFinanceTripApply.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return bo;
    }

    /**
     * 修改出差申请
     */
    @Override
    public OaFinanceTripApply updateByBo(OaFinanceTripApplyBo bo) {
        OaFinanceTripApply update = BeanUtil.toBean(bo, OaFinanceTripApply.class);
        validEntityBeforeSave(update);
        baseMapper.updateById(update);
        return update;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OaFinanceTripApply entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除出差申请
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
            for (String id : ids) {
                String processInstanceId = iProcessInstanceService.getProcessInstanceId(id);
                if (StringUtils.isNotBlank(processInstanceId)) {
                    iProcessInstanceService.deleteRuntimeProcessAndHisInst(processInstanceId);
                }
            }
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<OaProject> getProjectList(){
        List<OaProject> list = oaProjectService.getProjectName();
        List<OaFinanceTripApply> tripApplyList = baseMapper.selectList();
        List<String> collect = tripApplyList.stream().map(OaFinanceTripApply::getProjectName).collect(Collectors.toList());
        list=list.stream().filter(d->{
            if (collect.indexOf(d.getProjectName())==-1){
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        return list;
    }

    @Override
    public OaFinanceTripApplyVo queryByProjectName(String projectName) {
        LambdaQueryWrapper<OaFinanceTripApply> lqw = Wrappers.lambdaQuery();
        lqw.eq(OaFinanceTripApply::getProjectName, projectName);
        OaFinanceTripApplyVo vo = baseMapper.selectVoOne(lqw);
        if (ObjectUtil.isEmpty(vo)){
            return null;
        }
        WorkFlowUtils.setStatusFileValue(vo,vo.getId());
        return vo;
    }


    public void sysTrip(String id){
        OaFinanceTripApplyVo oaFinanceTripApplyVo = queryById(id);
        iOaHumanClockService.sysTrip(oaFinanceTripApplyVo);
    }


    @Override
    public Integer getUserTripByMonth(String month, String userId) {
        List<OaFinanceTripApplyVo> list = baseMapper.getUserTripByMonth(month, userId);
        if (CollectionUtil.isNotEmpty(list)) {
            List<String> Idlist = list.stream().map(OaFinanceTripApplyVo::getId).collect(Collectors.toList());
            WorkFlowUtils.setStatusListFileValue(list, Idlist, "id");
        }

        if (CollectionUtil.isNotEmpty(list)) {
            list = list.stream().filter(d -> d.getActBusinessStatus().getStatus().equals("finish")).collect(Collectors.toList());
        }

        return list.size();
    }
}
